home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / nasm095s.zip / INSNS.PL < prev    next >
Perl Script  |  1997-07-27  |  5KB  |  162 lines

  1. #!/usr/bin/perl
  2. #
  3. # insns.pl   produce insnsa.c and insnsd.c from insns.dat
  4. #
  5. # The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  6. # Julian Hall. All rights reserved. The software is
  7. # redistributable under the licence given in the file "Licence"
  8. # distributed in the NASM archive.
  9.  
  10. print STDERR "Reading insns.dat...\n";
  11.  
  12. open (F, "insns.dat") || die "unable to open insns.dat";
  13.  
  14. $line = 0;
  15. $opcodes = 0;
  16. $insns = 0;
  17. while (<F>) {
  18.   $line++;
  19.   next if /^\s*;/;   # comments
  20.   chomp;
  21.   split;
  22.   next if $#_ == -1; # blank lines
  23.   (warn "line $line does not contain four fields\n"), next if $#_ != 3;
  24.   ($formatted, $nd) = &format(@_);
  25.   if ($formatted) {
  26.     $insns++;
  27.     $aname = "aa_$_[0]";
  28.     push @$aname, $formatted;
  29.   }
  30.   $opcodes[$opcodes++] = $_[0], $done{$_[0]} = 1 if !$done{$_[0]};
  31.   if ($formatted && !$nd) {
  32.     push @big, $formatted;
  33.     foreach $i (&startbyte($_[2])) {
  34.       $aname = sprintf "dd_%02X",$i;
  35.       push @$aname, $#big;
  36.     }
  37.   }
  38. }
  39.  
  40. close F;
  41.  
  42. print STDERR "Writing insnsa.c...\n";
  43.  
  44. open A, ">insnsa.c";
  45.  
  46. print A "/* This file auto-generated from insns.dat by insns.pl" .
  47.         " - don't edit it */\n\n";
  48. print A "#include <stdio.h>\n";
  49. print A "#include \"nasm.h\"\n";
  50. print A "#include \"insns.h\"\n";
  51. print A "\n";
  52.  
  53. foreach $i (@opcodes) {
  54.   print A "static struct itemplate instrux_${i}[] = {\n";
  55.   $aname = "aa_$i";
  56.   foreach $j (@$aname) {
  57.     print A "    $j\n";
  58.   }
  59.   print A "    {-1}\n};\n\n";
  60. }
  61. print A "struct itemplate *nasm_instructions[] = {\n";
  62. foreach $i (@opcodes) {
  63.   print A "    instrux_${i},\n";
  64. }
  65. print A "};\n";
  66.  
  67. close A;
  68.  
  69. print STDERR "Writing insnsd.c...\n";
  70.  
  71. open D, ">insnsd.c";
  72.  
  73. print D "/* This file auto-generated from insns.dat by insns.pl" .
  74.         " - don't edit it */\n\n";
  75. print D "#include <stdio.h>\n";
  76. print D "#include \"nasm.h\"\n";
  77. print D "#include \"insns.h\"\n";
  78. print D "\n";
  79.  
  80. print D "static struct itemplate instrux[] = {\n";
  81. foreach $j (@big) {
  82.   print D "    $j\n";
  83. }
  84. print D "    {-1}\n};\n\n";
  85.  
  86. for ($c=0; $c<256; $c++) {
  87.   $h = sprintf "%02X", $c;
  88.   print D "static struct itemplate *itable_${h}[] = {\n";
  89.   $aname = "dd_$h";
  90.   foreach $j (@$aname) {
  91.     print D "    instrux + $j,\n";
  92.   }
  93.   print D "    NULL\n};\n\n";
  94. }
  95.  
  96. print D "struct itemplate **itable[] = {\n";
  97. for ($c=0; $c<256; $c++) {
  98.   printf D "    itable_%02X,\n", $c;
  99. }
  100. print D "};\n";
  101.  
  102. close D;
  103.  
  104. printf STDERR "Done: %d instructions\n", $insns;
  105.  
  106. sub format {
  107.   local ($opcode, $operands, $codes, $flags) = @_;
  108.   local $num, $nd = 0;
  109.  
  110.   return (undef, undef) if $operands eq "ignore";
  111.  
  112.   # format the operands
  113.   $operands =~ s/:/|colon,/g;
  114.   $operands =~ s/mem(\d+)/mem|bits$1/g;
  115.   $operands =~ s/mem/memory/g;
  116.   $operands =~ s/memory_offs/mem_offs/g;
  117.   $operands =~ s/imm(\d+)/imm|bits$1/g;
  118.   $operands =~ s/imm/immediate/g;
  119.   $operands =~ s/rm(\d+)/regmem|bits$1/g;
  120.   $num = 3;
  121.   $operands = '0,0,0', $num = 0 if $operands eq 'void';
  122.   $operands .= ',0', $num-- while $operands !~ /,.*,/;
  123.   $operands =~ tr/a-z/A-Z/;
  124.  
  125.   # format the flags
  126.   $flags =~ s/,/|IF_/g;
  127.   $flags =~ s/(\|IF_ND|IF_ND\|)//, $nd = 1 if $flags =~ /IF_ND/;
  128.   $flags = "IF_" . $flags;
  129.  
  130.   ("{I_$opcode, $num, {$operands}, \"$codes\", $flags},", $nd);
  131. }
  132.  
  133. # Here we determine the range of possible starting bytes for a given
  134. # instruction. We need only consider the codes:
  135. # \1 \2 \3     mean literal bytes, of course
  136. # \4 \5 \6 \7  mean PUSH/POP of segment registers: special case
  137. # \10 \11 \12  mean byte plus register value
  138. # \17          means byte zero
  139. # \330         means byte plus condition code
  140. # \0 or \340   mean give up and return empty set
  141. sub startbyte {
  142.   local ($codes) = @_;
  143.   local $word, @range;
  144.  
  145.   while (1) {
  146.     die "couldn't get code in '$codes'" if $codes !~ /^(\\[^\\]+)(\\.*)?$/;
  147.     $word = $1, $codes = $2;
  148.     return (hex $1) if $word =~ /^\\[123]$/ && $codes =~ /^\\x(..)/;
  149.     return (0x07, 0x17, 0x1F) if $word eq "\\4";
  150.     return (0xA1, 0xA9) if $word eq "\\5";
  151.     return (0x06, 0x0E, 0x16, 0x1E) if $word eq "\\6";
  152.     return (0xA0, 0xA8) if $word eq "\\7";
  153.     $start=hex $1, $r=8, last if $word =~ /^\\1[012]$/ && $codes =~/^\\x(..)/;
  154.     return (0) if $word eq "\\17";
  155.     $start=hex $1, $r=16, last if $word =~ /^\\330$/ && $codes =~ /^\\x(..)/;
  156.     return () if $word eq "\\0" || $word eq "\\340";
  157.   }
  158.   @range = ();
  159.   push @range, $start++ while ($r-- > 0);
  160.   @range;
  161. }
  162.